#include <inctypes.h>
#include <incctrls.h>

/*********************************************************************************
* 
* krl_thdkrlstk_init - 进程内核栈初始化
* 
* DESCRIPTION
*/

void krl_thdkrlstk_init 
    (
    thread_t * thdp, 
    void *     thdfunc, 
    reg_t      cpsr,
    reg_t      spsr
    )
    {

    /* 栈对齐 (16字节对齐) */ 
    
    thdp->usrstktop &= (~0xF);
    thdp->krlstktop &= (~0xF);

    /*
     * 从栈顶减去一个 armregs_t 结构体大小, 并让 armregs_t 结构的指针指向这个地址,
     * 相当于在进程内核栈中让出一个 armregs_t 结构体的空间, 在该空间内初始化 CPU 的
     * ro ~ r14 这15个寄存器(高地址栈单元放序号大的寄存器)，r0 ~ r12 寄存器对应的值
     * 为 0, r13 寄存器对应的值为进程用户栈指针, r14 寄存器对应的值为进程主函数的地
     * 址 (栈的生长方向 (向低地址增长)).
     */

    armregs_t * argp = (armregs_t *) (thdp->krlstktop - sizeof (armregs_t));

    argp->r0  = 0;
    argp->r1  = 0;
    argp->r2  = 0;
    argp->r3  = 0;
    argp->r4  = 0;
    argp->r5  = 0;
    argp->r6  = 0;
    argp->r7  = 0;
    argp->r8  = 0;
    argp->r9  = 0;
    argp->r10 = 0;
    argp->r11 = 0;
    argp->r12 = 0;
    argp->r13 = (reg_t) (thdp->usrstktop);
    argp->r14 = (reg_t) thdfunc; 

    /* 初始化 进程上下文的 context_t 结构体  */

    thdp->context.usrsp   = (reg_t) (thdp->usrstktop); /* 保存 用户模式下的栈指针地址 */
    thdp->context.svcsp   = (reg_t) (argp);            /* 保存 内核模式下的栈指针地址 */
    thdp->context.svcspsr = spsr;                      /* 保存 内核模式下的备份程序状态寄存器 */
    thdp->context.cpsr    = cpsr;                      /* 保存 当前程序状态状态存器 */
    thdp->context.usrlr   = (reg_t) thdfunc;           /* 保存 用户模式下的链接寄存器 */

    return;
    }

/*********************************************************************************
* 
* context_t_init - 初始化 context_t 结构体
* 
* DESCRIPTION
*/

void context_t_init 
    (
    context_t * initp
    )
    {
    initp->usrsp   = 0;
    initp->svcsp   = 0;
    initp->svcspsr = 0;
    initp->cpsr    = 0;
    initp->usrlr   = 0;
    
    return;
    }

/*********************************************************************************
* 
* krl_return_thdid - 获得进程ID
* 
* DESCRIPTION
*/

uint_t krl_return_thdid
    (
    thread_t * thdp
    )
    {
    uint_t thdid;

    thdid = (uint_t) thdp;

    return thdid;
    }

/*********************************************************************************
* 
* thread_t_init - 初始化 thread_t 结构体
* 
* DESCRIPTION
*/

void thread_t_init
    (
    thread_t * initp
    )
    {
    uint_t i;

    /* 参数有效性检查 */

    if (initp == NULL)
        {
        return;
        }

    /* 初始化自旋锁 */

    hal_spinlock_init (&initp->lock);

    /* 初始化链表 */

    list_init (&initp->list);

    /* 初始化其他成员  */

    initp->flag        = 0;
    initp->status      = THDSTUS_NEW;              /* 进程状态为新建 */
    initp->cpuid       = hal_get_cpuid ();         /* 获取进程所在CPUID */
    initp->id          = krl_return_thdid (initp); /* 获取进程ID */
    initp->tick        = 0;                        /* 初始化时间片为0 */
    initp->privalege   = THDPRILG_USR;             /* 普通用户进程 */
    initp->priority    = THDPRI_HIGHEST;           /* 默认为最高优先级 */
    initp->runmode     = 0;                        /* 运行模式 */

    /* 初始化进程栈地址 */

    initp->krlstktop   = NULL;
    initp->krlstkstart = NULL;
    initp->usrstktop   = NULL;
    initp->usrstkstart = NULL;

    initp->memdsc      = NULL;              /* 内存描述符 */
    
    /* 初始化 context_t 结构体 */

    context_t_init (&initp->context);

    /* 初始化进程的所有设备资源为NULL */

    for (i = 0; i < THD_SRC_MAX_NBR; i++)
        {
        initp->srctbl[i] = NULL;
        }

    return;
    }

/*********************************************************************************
* 
* krl_create_thddsc - 创建进程描述符
* 
* DESCRIPTION
*/

thread_t * krl_create_thddsc (void)
    {

    /* 分配 thread_t 结构实例变量的内存空间 */

    thread_t * thdp = (thread_t *) krl_mem_new (sizeof (thread_t));

    if (thdp == NULL)
        {
        return NULL;
        }

    /* 初始化 thread_t 结构体 */

    thread_t_init (thdp);

    return thdp;
    }

/*********************************************************************************
* 
* krl_create_thread_core - 新建进程的核心函数
* 
* DESCRIPTION
*/

thread_t * krl_create_thread_core
    (
    void * thdfunc,
    uint_t flag,
    uint_t privalege,
    uint_t priority,
    size_t usrstksz,
    size_t krlstksz
    )
    {
    thread_t * thdp       = NULL;
    addr_t     usrstkaddr = NULL, krlstkaddr = NULL;
    
    /* 分配用户栈 */

    usrstkaddr = krl_mem_new (usrstksz);

    if (usrstkaddr == NULL)
        {
        return NULL; /* 分配失败 */
        }

    /* 分配内核栈 */

    krlstkaddr = krl_mem_new (krlstksz);

    if (krlstkaddr == NULL)
        {
        goto krlstk_create_fail;  /* 分配内核栈失败, 释放用户栈 */
        }

    /* 分配进程描述符 */

    thdp = krl_create_thddsc ();

    if (thdp == NULL)
        {
        goto thddsc_create_fail;  /* 创建进程描述符失败, 释放用户栈和内核栈 */
        }

    /* 初始化成员变量 */

    thdp->privalege = privalege;        /* 设置进程权限 */
    thdp->priority  = priority;         /* 设置进程优先级 */
    thdp->cpuid     = hal_get_cpuid (); /* 设置进程所在的CPU ID  */

    /* 设置用户栈和内核栈的栈顶地址和栈的开始地址 */

    thdp->usrstktop   = usrstkaddr + (addr_t) (usrstksz - 1);
    thdp->usrstkstart = usrstkaddr;
    thdp->krlstktop   = krlstkaddr + (addr_t) (krlstksz - 1);
    thdp->krlstkstart = krlstkaddr;

    /* 进程内核栈初始化 */

    krl_thdkrlstk_init (thdp, (void *) thdfunc, DAFT_CPSR, DAFT_IDLESPSR);

    /* 把进程加入进程调度表中 */

    krl_sched_add_thd_to_schedtbl (thdp);

    /* 创建成功, 返回进程描述符 */

    return thdp;

thddsc_create_fail:

    /* 释放内核栈 */

    if (krl_mem_delete (krlstkaddr, krlstksz) == FALSE)
        {
        krl_system_die ("krl_create_thread_core err\r\n");
        return NULL;
        }

krlstk_create_fail:

    /* 释放用户栈 */

    if (krl_mem_delete (usrstkaddr, usrstksz) == FALSE)
        {
        krl_system_die ("krl_create_thread_core err\r\n");
        return NULL;
        }

    return NULL;
    }

/*********************************************************************************
* 
* krl_create_thread - 创建进程的接口函数
* 
* DESCRIPTION
*/

thread_t * krl_create_thread
    (
    void * thdfunc,
    uint_t flag,
    uint_t privalege,
    uint_t priority,
    size_t usrstksz,
    size_t krlstksz
    )
    {
    size_t     ustksz = 0, kstksz = 0;
    thread_t * thdp   = NULL;;

    /* 检查 flag, thdfunc, 进程栈的有效性 */

    if (((flag & 0x1) != 0) || (thdfunc == NULL) || 
        (usrstksz > DAFT_THDSTKUSR_SZ) || (krlstksz > DAFT_THDSTKKRL_SZ))
        {
        return NULL;
        }

    /* 检查优先级和特权参数有效性 */

    if (((privalege != THDPRILG_USR) && (privalege != THDPRILG_SYS)) ||
        ((priority < THDPRI_MIN) || (priority > THDPRI_MAX)))
        {
        return NULL;
        }

    /* 进程栈限制大小 */

    if (usrstksz < DAFT_THDSTKUSR_SZ)
        {
        ustksz = DAFT_THDSTKUSR_SZ;   /* 用户栈限制大小 */
        }

    if (krlstksz < DAFT_THDSTKKRL_SZ)
        {
        kstksz = DAFT_THDSTKKRL_SZ;   /* 内核栈限制大小 */
        }

    /* 调用创建进程核心函数创建进程 */

    thdp = krl_create_thread_core (thdfunc, flag, privalege, priority, ustksz, kstksz);

    return thdp;
    }

/*********************************************************************************
* 
* krl_inc_thdtick - 增加当前运行进程的 TICK 值
* 
* DESCRIPTION
*/

void krl_inc_thdtick
    (
    thread_t * thdp
    )
    {
    cpuflg_t cpuflg;

    /* 进程数据结构 自旋锁 加锁 */

    spinlock_saveflg_cli (&thdp->lock, &cpuflg);
    
    /* tick +1 */

    thdp->tick++;

    /* 检查进程 tick 是否大于 THD_SYS_TICK */

    if (thdp->tick >= THD_SYS_TICK)
        {
        thdp->tick = 0;                 /* 计数值复位 */
        krl_sched_set_schedflag ();     /* 设置内核调度标志 (准备调度) */
        }

    /* 进程数据结构 自旋锁 解锁 */

    spinunlock_restflg_sti (&thdp->lock, &cpuflg);

    return;
    }

/*********************************************************************************
* 
* krl_thd_add_objnode - 把一个 objnode_t (IO包) 加入进程资源数组中
* 
* DESCRIPTION
*/

hand_t krl_thd_add_objnode
    (
    thread_t *  thdp,
    objnode_t * objndp
    )
    {
    cpuflg_t cpuflg;
    hand_t   rethand;
    uint_t   i;

    /* 进程数据结构 自旋锁 加锁 */

    spinlock_saveflg_cli (&thdp->lock, &cpuflg);

    /* 扫描该进程的资源数组 */

    for (i = 0; i < THD_SRC_MAX_NBR; i++)
        {
        
        /* 判断第 i 个资源是否为 NULL */

        if (thdp->srctbl[i] == NULL)
            {
            rethand = i;

            goto next_step;
            }

        }

    /* thdp 进程资源数组中 不存在 NULL */

    rethand = (hand_t) -1;
    goto return_step;

next_step:

    /* 把 objndp 加进 thdp 资源数组中 */

    thdp->srctbl[i] = objndp;

return_step:

    /* 进程数据结构 自旋锁 解锁 */

    spinunlock_restflg_sti (&thdp->lock, &cpuflg);

    return rethand;
    }

/*********************************************************************************
* 
* krl_thd_delete_objnode - 把一个 objnode_t (IO包) 从进程资源数组中删除
* 
* DESCRIPTION
*/

hand_t krl_thd_delete_objnode
    (
    thread_t * thdp, 
    hand_t     handidx
    )
    {
    cpuflg_t cpuflg;
    hand_t   rethand;

    /* 检验参数有效性 */

    if ((handidx >= THD_SRC_MAX_NBR) || (handidx <= THD_SRC_NUL_NBR))
        {
        return -1;
        }

    /* 进程数据结构 自旋锁 加锁 */

    spinlock_saveflg_cli (&thdp->lock, &cpuflg);

    /* 如果进程资源数组的 第handidx为NULL, 则出现错误 */

    if (thdp->srctbl[handidx] == NULL)
        {
        rethand = -1;
        goto return_step;
        }

    /* 设置进程资源组的 第handidx为NULL */

    thdp->srctbl[rethand] = NULL;
    rethand = handidx;

return_step:

    /* 进程数据结构 自旋锁 解锁 */

    spinunlock_restflg_sti (&thdp->lock, &cpuflg);

    return rethand;
    }

/*********************************************************************************
* 
* krl_thd_return_objnode - 返回一个 thread 的指定 hand 序号的 onjnode
* 
* DESCRIPTION
*/

objnode_t * krl_thd_return_objnode 
    (
    thread_t * thdp,
    hand_t     handidx
    )
    {
    cpuflg_t    cpuflg;
    objnode_t * retobjnd = NULL;

    /* 检验参数有效性 */

    if ((handidx >= THD_SRC_MAX_NBR) || (handidx <= THD_SRC_NUL_NBR))
        {
        return NULL;
        }

    /* 进程数据结构 自旋锁 加锁 */

    spinlock_saveflg_cli (&thdp->lock, &cpuflg);
    
    /* 如果进程资源数组的 第handidx为NULL, 则出现错误 */

    if(thdp->srctbl[handidx] == NULL)
        {
        retobjnd = NULL;
        goto return_step;
        }

    /* 找到并返回 */

    retobjnd = thdp->srctbl[handidx];

return_step:

    /* 进程数据结构 自旋锁 解锁 */

    spinunlock_restflg_sti (&thdp->lock, &cpuflg);
    
    return retobjnd;
    }